//-----------------------------------------------------------------------------
//     Author : hiyohiyo
//       Mail : hiyohiyo@crystalmark.info
//        Web : http://openlibsys.org/
//    License : The modified BSD license
//
//                     Copyright 2007-2020 OpenLibSys.org. All rights reserved.
//-----------------------------------------------------------------------------
// for WinRing0 3.0.x

#pragma once

#include <windows.h>
#include "OlsApiInitDef.h"
#include "MemoryModule.h"
#include "resource.h"
//-----------------------------------------------------------------------------
//
// Prototypes
//
//-----------------------------------------------------------------------------

BOOL InitOpenLibSys(HMEMORYMODULE hModule);
BOOL DeinitOpenLibSys(HMEMORYMODULE hModule);

//-----------------------------------------------------------------------------
//
// Funtions
//
//-----------------------------------------------------------------------------

// DLL
_GetDllStatus GetDllStatus = NULL;
_GetDllVersion GetDllVersion = NULL;
_GetDriverVersion GetDriverVersion = NULL;
_GetDriverType GetDriverType = NULL;

_InitializeOls InitializeOls = NULL;
_DeinitializeOls DeinitializeOls = NULL;

// CPU
_IsCpuid IsCpuid = NULL;
_IsMsr IsMsr = NULL;
_IsTsc IsTsc = NULL;

_Hlt Hlt = NULL;
_Rdmsr Rdmsr = NULL;
_Wrmsr Wrmsr = NULL;
_Rdpmc Rdpmc = NULL;
_Cpuid Cpuid = NULL;
_Rdtsc Rdtsc = NULL;

_HltTx HltTx = NULL;
_RdmsrTx RdmsrTx = NULL;
_WrmsrTx WrmsrTx = NULL;
_RdpmcTx RdpmcTx = NULL;
_CpuidTx CpuidTx = NULL;
_RdtscTx RdtscTx = NULL;

_HltPx HltPx = NULL;
_RdmsrPx RdmsrPx = NULL;
_WrmsrPx WrmsrPx = NULL;
_RdpmcPx RdpmcPx = NULL;
_CpuidPx CpuidPx = NULL;
_RdtscPx RdtscPx = NULL;

// I/O
_ReadIoPortByte ReadIoPortByte = NULL;
_ReadIoPortWord ReadIoPortWord = NULL;
_ReadIoPortDword ReadIoPortDword = NULL;

_ReadIoPortByteEx ReadIoPortByteEx = NULL;
_ReadIoPortWordEx ReadIoPortWordEx = NULL;
_ReadIoPortDwordEx ReadIoPortDwordEx = NULL;

_WriteIoPortByte WriteIoPortByte = NULL;
_WriteIoPortWord WriteIoPortWord = NULL;
_WriteIoPortDword WriteIoPortDword = NULL;

_WriteIoPortByteEx WriteIoPortByteEx = NULL;
_WriteIoPortWordEx WriteIoPortWordEx = NULL;
_WriteIoPortDwordEx WriteIoPortDwordEx = NULL;

// PCI
_SetPciMaxBusIndex SetPciMaxBusIndex = NULL;

_ReadPciConfigByte ReadPciConfigByte = NULL;
_ReadPciConfigWord ReadPciConfigWord = NULL;
_ReadPciConfigDword ReadPciConfigDword = NULL;

_ReadPciConfigByteEx ReadPciConfigByteEx = NULL;
_ReadPciConfigWordEx ReadPciConfigWordEx = NULL;
_ReadPciConfigDwordEx ReadPciConfigDwordEx = NULL;

_WritePciConfigByte WritePciConfigByte = NULL;
_WritePciConfigWord WritePciConfigWord = NULL;
_WritePciConfigDword WritePciConfigDword = NULL;

_WritePciConfigByteEx WritePciConfigByteEx = NULL;
_WritePciConfigWordEx WritePciConfigWordEx = NULL;
_WritePciConfigDwordEx WritePciConfigDwordEx = NULL;

_FindPciDeviceById FindPciDeviceById = NULL;
_FindPciDeviceByClass FindPciDeviceByClass = NULL;

// Memory
#ifdef _PHYSICAL_MEMORY_SUPPORT
_ReadDmiMemory ReadDmiMemory = NULL;
_ReadPhysicalMemory ReadPhysicalMemory = NULL;
_WritePhysicalMemory WritePhysicalMemory = NULL;
#endif

#ifdef _OPEN_LIB_SYS
#ifdef _UNICODE
#define GetOlsString GetOlsStringW
#else
#define GetOlsString GetOlsStringA
#endif

_InstallOpenLibSys InstallOpenLibSys = NULL;
_UninstallOpenLibSys UninstallOpenLibSys = NULL;
_GetDriverStatus GetDriverStatus = NULL;

_GetOlsStringA GetOlsStringA = NULL;
_GetOlsStringW GetOlsStringW = NULL;
_GetOlsValue GetOlsValue = NULL;
_SetOlsValue SetOlsValue = NULL;
#endif

//-----------------------------------------------------------------------------
//
// Initialize
//
//-----------------------------------------------------------------------------

BOOL InitOpenLibSys(HMEMORYMODULE hModule)
{
	//HMODULE hInstance = ::GetModuleHandle(NULL);
#ifdef _M_X64
	HMODULE hInstance = ::GetModuleHandle(TEXT("IOEngine.cp38-win_amd64.pyd"));
	HRSRC resourceInfo = FindResource(hInstance, MAKEINTRESOURCE(IDR_DLL64), TEXT("DLL"));
#else
	HMODULE hInstance = ::GetModuleHandle(TEXT("IOEngine.cp38-win32.pyd"));
	HRSRC resourceInfo = FindResource(hInstance, MAKEINTRESOURCE(IDR_DLL32), TEXT("DLL"));
#endif
	if (resourceInfo == NULL)
	{
		return FALSE;
	}
	HGLOBAL resourceHandle = LoadResource(hInstance, resourceInfo);
	if (resourceHandle == NULL)
	{
		return FALSE;
	}
	DWORD resourceSize = SizeofResource(hInstance, resourceInfo);
	LPVOID resourceData = LockResource(resourceHandle);
	hModule = MemoryLoadLibrary(resourceData, resourceSize);
	if (hModule == NULL)
	{
		return FALSE;
	}

	//-----------------------------------------------------------------------------
	// MemoryGetProcAddress
	//-----------------------------------------------------------------------------
	// DLL
	GetDllStatus = (_GetDllStatus)MemoryGetProcAddress(hModule, "GetDllStatus");
	GetDllVersion = (_GetDllVersion)MemoryGetProcAddress(hModule, "GetDllVersion");
	GetDriverVersion = (_GetDriverVersion)MemoryGetProcAddress(hModule, "GetDriverVersion");
	GetDriverType = (_GetDriverType)MemoryGetProcAddress(hModule, "GetDriverType");

	InitializeOls = (_InitializeOls)MemoryGetProcAddress(hModule, "InitializeOls");
	DeinitializeOls = (_DeinitializeOls)MemoryGetProcAddress(hModule, "DeinitializeOls");

	// CPU
	IsCpuid = (_IsCpuid)MemoryGetProcAddress(hModule, "IsCpuid");
	IsMsr = (_IsMsr)MemoryGetProcAddress(hModule, "IsMsr");
	IsTsc = (_IsTsc)MemoryGetProcAddress(hModule, "IsTsc");
	Hlt = (_Hlt)MemoryGetProcAddress(hModule, "Hlt");
	Rdmsr = (_Rdmsr)MemoryGetProcAddress(hModule, "Rdmsr");
	Wrmsr = (_Wrmsr)MemoryGetProcAddress(hModule, "Wrmsr");
	Rdpmc = (_Rdpmc)MemoryGetProcAddress(hModule, "Rdpmc");
	Cpuid = (_Cpuid)MemoryGetProcAddress(hModule, "Cpuid");
	Rdtsc = (_Rdtsc)MemoryGetProcAddress(hModule, "Rdtsc");
	HltTx = (_HltTx)MemoryGetProcAddress(hModule, "HltTx");
	RdmsrTx = (_RdmsrTx)MemoryGetProcAddress(hModule, "RdmsrTx");
	WrmsrTx = (_WrmsrTx)MemoryGetProcAddress(hModule, "WrmsrTx");
	RdpmcTx = (_RdpmcTx)MemoryGetProcAddress(hModule, "RdpmcTx");
	CpuidTx = (_CpuidTx)MemoryGetProcAddress(hModule, "CpuidTx");
	RdtscTx = (_RdtscTx)MemoryGetProcAddress(hModule, "RdtscTx");
	HltPx = (_HltPx)MemoryGetProcAddress(hModule, "HltPx");
	RdmsrPx = (_RdmsrPx)MemoryGetProcAddress(hModule, "RdmsrPx");
	WrmsrPx = (_WrmsrPx)MemoryGetProcAddress(hModule, "WrmsrPx");
	RdpmcPx = (_RdpmcPx)MemoryGetProcAddress(hModule, "RdpmcPx");
	CpuidPx = (_CpuidPx)MemoryGetProcAddress(hModule, "CpuidPx");
	RdtscPx = (_RdtscPx)MemoryGetProcAddress(hModule, "RdtscPx");

	// I/O
	ReadIoPortByte = (_ReadIoPortByte)MemoryGetProcAddress(hModule, "ReadIoPortByte");
	ReadIoPortWord = (_ReadIoPortWord)MemoryGetProcAddress(hModule, "ReadIoPortWord");
	ReadIoPortDword = (_ReadIoPortDword)MemoryGetProcAddress(hModule, "ReadIoPortDword");

	ReadIoPortByteEx = (_ReadIoPortByteEx)MemoryGetProcAddress(hModule, "ReadIoPortByteEx");
	ReadIoPortWordEx = (_ReadIoPortWordEx)MemoryGetProcAddress(hModule, "ReadIoPortWordEx");
	ReadIoPortDwordEx = (_ReadIoPortDwordEx)MemoryGetProcAddress(hModule, "ReadIoPortDwordEx");

	WriteIoPortByte = (_WriteIoPortByte)MemoryGetProcAddress(hModule, "WriteIoPortByte");
	WriteIoPortWord = (_WriteIoPortWord)MemoryGetProcAddress(hModule, "WriteIoPortWord");
	WriteIoPortDword = (_WriteIoPortDword)MemoryGetProcAddress(hModule, "WriteIoPortDword");

	WriteIoPortByteEx = (_WriteIoPortByteEx)MemoryGetProcAddress(hModule, "WriteIoPortByteEx");
	WriteIoPortWordEx = (_WriteIoPortWordEx)MemoryGetProcAddress(hModule, "WriteIoPortWordEx");
	WriteIoPortDwordEx = (_WriteIoPortDwordEx)MemoryGetProcAddress(hModule, "WriteIoPortDwordEx");

	// PCI
	SetPciMaxBusIndex = (_SetPciMaxBusIndex)MemoryGetProcAddress(hModule, "SetPciMaxBusIndex");

	ReadPciConfigByte = (_ReadPciConfigByte)MemoryGetProcAddress(hModule, "ReadPciConfigByte");
	ReadPciConfigWord = (_ReadPciConfigWord)MemoryGetProcAddress(hModule, "ReadPciConfigWord");
	ReadPciConfigDword = (_ReadPciConfigDword)MemoryGetProcAddress(hModule, "ReadPciConfigDword");

	ReadPciConfigByteEx = (_ReadPciConfigByteEx)MemoryGetProcAddress(hModule, "ReadPciConfigByteEx");
	ReadPciConfigWordEx = (_ReadPciConfigWordEx)MemoryGetProcAddress(hModule, "ReadPciConfigWordEx");
	ReadPciConfigDwordEx = (_ReadPciConfigDwordEx)MemoryGetProcAddress(hModule, "ReadPciConfigDwordEx");

	WritePciConfigByte = (_WritePciConfigByte)MemoryGetProcAddress(hModule, "WritePciConfigByte");
	WritePciConfigWord = (_WritePciConfigWord)MemoryGetProcAddress(hModule, "WritePciConfigWord");
	WritePciConfigDword = (_WritePciConfigDword)MemoryGetProcAddress(hModule, "WritePciConfigDword");

	WritePciConfigByteEx = (_WritePciConfigByteEx)MemoryGetProcAddress(hModule, "WritePciConfigByteEx");
	WritePciConfigWordEx = (_WritePciConfigWordEx)MemoryGetProcAddress(hModule, "WritePciConfigWordEx");
	WritePciConfigDwordEx = (_WritePciConfigDwordEx)MemoryGetProcAddress(hModule, "WritePciConfigDwordEx");

	FindPciDeviceById = (_FindPciDeviceById)MemoryGetProcAddress(hModule, "FindPciDeviceById");
	FindPciDeviceByClass = (_FindPciDeviceByClass)MemoryGetProcAddress(hModule, "FindPciDeviceByClass");

	// Memory
#ifdef _PHYSICAL_MEMORY_SUPPORT
	ReadDmiMemory = (_ReadDmiMemory)MemoryGetProcAddress(hModule, "ReadDmiMemory");
	ReadPhysicalMemory = (_ReadPhysicalMemory)MemoryGetProcAddress(hModule, "ReadPhysicalMemory");
	WritePhysicalMemory = (_WritePhysicalMemory)MemoryGetProcAddress(hModule, "WritePhysicalMemory");
#endif

	//-----------------------------------------------------------------------------
	// Check Functions
	//-----------------------------------------------------------------------------
	if (!(
		GetDllStatus
		&& GetDllVersion
		&& GetDriverVersion
		&& GetDriverType
		&& InitializeOls
		&& DeinitializeOls
		&& IsCpuid
		&& IsMsr
		&& IsTsc
		&& Hlt
		&& HltTx
		&& HltPx
		&& Rdmsr
		&& RdmsrTx
		&& RdmsrPx
		&& Wrmsr
		&& WrmsrTx
		&& WrmsrPx
		&& Rdpmc
		&& RdpmcTx
		&& RdpmcPx
		&& Cpuid
		&& CpuidTx
		&& CpuidPx
		&& Rdtsc
		&& RdtscTx
		&& RdtscPx
		&& ReadIoPortByte
		&& ReadIoPortWord
		&& ReadIoPortDword
		&& ReadIoPortByteEx
		&& ReadIoPortWordEx
		&& ReadIoPortDwordEx
		&& WriteIoPortByte
		&& WriteIoPortWord
		&& WriteIoPortDword
		&& WriteIoPortByteEx
		&& WriteIoPortWordEx
		&& WriteIoPortDwordEx
		&& SetPciMaxBusIndex
		&& ReadPciConfigByte
		&& ReadPciConfigWord
		&& ReadPciConfigDword
		&& ReadPciConfigByteEx
		&& ReadPciConfigWordEx
		&& ReadPciConfigDwordEx
		&& WritePciConfigByte
		&& WritePciConfigWord
		&& WritePciConfigDword
		&& WritePciConfigByteEx
		&& WritePciConfigWordEx
		&& WritePciConfigDwordEx
		&& FindPciDeviceById
		&& FindPciDeviceByClass
#ifdef _PHYSICAL_MEMORY_SUPPORT
		&& ReadDmiMemory
		&& ReadPhysicalMemory
		&& WritePhysicalMemory
#endif
		))
	{
		return FALSE;
	}
	return InitializeOls();
}

//-----------------------------------------------------------------------------
//
// Deinitialize
//
//-----------------------------------------------------------------------------

BOOL DeinitOpenLibSys(HMEMORYMODULE hModule)
{
	if (hModule == NULL)
	{
		return TRUE;
	}
	else
	{
		DeinitializeOls();
		MemoryFreeLibrary(hModule);
		hModule = NULL;
		return TRUE;
	}
}

